package com.ideaaedi.springcloud.jd.user.mybatisplus;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Property;
import com.ideaaedi.commonds.io.IOUtil;
import com.ideaaedi.commonds.path.PathUtil;
import com.ideaaedi.springcloud.jd.commonds.entity.BaseDTO;
import com.ideaaedi.springcloud.jd.commonds.entity.BasePageDTO;
import com.ideaaedi.springcloud.jd.commonds.entity.PageInfo;
import com.ideaaedi.springcloud.jd.commonds.entity.Result;
import com.ideaaedi.springcloud.jd.user.UserApplication;
import lombok.Getter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * mybatis-plus代码生成 &emsp;
 * <a href="https://baomidou.com/pages/779a6e/#%E4%BD%BF%E7%94%A8">代码生成官网</a>
 * &emsp;
 * <a href="https://baomidou.com/pages/981406/#%E5%9F%BA%E7%A1%80%E9%85%8D%E7%BD%AE">配置说明官网</a>
 *
 * @author JustryDeng
 * @since 2022/6/28 9:26
 */
@SpringBootTest(classes = UserApplication.class)
public class MybatisPlusGeneratorHelper {
    
    private static final String javadocAuthor = "<font size = \"20\" color = \"#3CAA3C\"><a href=\"https://gitee"
            + ".com/JustryDeng\">JustryDeng</a></font> <img src=\"https://gitee"
            + ".com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg\" />";
    
    private static final String javadocSince = "'2021.0.5.B'";
    
    private static final String templateDir = "mybatis-plus-templates";
    
    @Value("${spring.datasource.url}")
    private String url;
    
    @Value("${spring.datasource.username}")
    private String username;
    
    @Value("${spring.datasource.password}")
    private String password;
    
    /**
     * true-使用自定义模板; false-使用默认模板
     */
    private static final boolean useCustomTemplate = true;
    
    /**
     * true-controller的返回模型用Result.success()包装; false-不包装
     * <p>
     * 注：只有当{@link MybatisPlusGeneratorHelper#useCustomTemplate}为true时，此参数才生效
     */
    private static final boolean wrapControllerResult = true;
    
    /**
     * 是否在PojoListRespVO模型的字段上添加@ExcelPropertyA注解
     */
    private static final boolean ifAddExcelPropertyAnno = true;
    
    /*
     * 自动生成模板文件
     */
    static {
        if (useCustomTemplate) {
            final String customTemplatesDirRePath = "/src/test/resources/" + templateDir + "/";
            String customTemplatesDirPath = PathUtil.getProjectRootDir(MybatisPlusGeneratorHelper.class)
                    .replace("/target/test-classes/", customTemplatesDirRePath);
            File customTemplatesDir = new File(customTemplatesDirPath);
            if (!customTemplatesDir.exists()) {
                System.err.println(MybatisPlusGeneratorHelper.class.getSimpleName() + "：自定义的模板文件不存在, 自动创建开始. 创建至：" + customTemplatesDirRePath);
                final String baseDTOName = BaseDTO.class.getName().replace("$", ".");
                final String basePageDTOName = BasePageDTO.class.getName().replace("$", ".");
                final String pageInfoName = PageInfo.class.getName().replace("$", ".");
                final String resultName = Result.class.getName().replace("$", ".");
                for (JustryDengTemplates templateInfo : JustryDengTemplates.values()) {
                    IOUtil.writeContentToFile(
                            templateInfo.getContent()
                                    .replace("JustryDeng_Placeholder.BaseDTO", baseDTOName)
                                    .replace("JustryDeng_Placeholder.BasePageDTO", basePageDTOName)
                                    .replace("JustryDeng_Placeholder.PageInfo", pageInfoName)
                                    .replace("JustryDeng_Placeholder.Result", resultName),
                            new File(customTemplatesDir, templateInfo.name));
                }
                System.err.println(MybatisPlusGeneratorHelper.class.getSimpleName() + "：自定义的模板文件创建完成. 请重新运行单元测试以生成相关文件.");
                System.exit(-1);
            }
        }
    }
    
    @Test
    void generate() {
        String outputRootDir = PathUtil.getProjectRootDir(MybatisPlusGeneratorHelper.class)
                .replace("/target/test-classes/", "/src/test/java/");
        String packagePath = MybatisPlusGeneratorHelper.class.getPackage().getName() + ".generator";
        // 先清空./generator/目录
        IOUtil.delete(new File(outputRootDir + packagePath.replace(".", "/")));
        
        
        // basic settings
        final FastAutoGenerator fastAutoGenerator = FastAutoGenerator
                .create(
                        new DataSourceConfig
                                .Builder(url, username, password)
                                .typeConvert((globalConfig, fieldType) -> {
                                    String columnType = fieldType.toLowerCase();
                                    // columnType形如 tinyint(2)  bit(1)
                                    if (columnType.startsWith("tinyint") || columnType.startsWith("bit")) {
                                        return DbColumnType.INTEGER;
                                    }
                                    // 其它字段采用默认转换
                                    return new MySqlTypeConvert().processTypeConvert(globalConfig, fieldType);
                                })
                )
                .globalConfig(builder -> builder
                        // 设置作者
                        .author(javadocAuthor)
                        .commentDate(javadocSince)
                        // 生成完成后，不打开对应目录
                        .disableOpenDir()
                        // 指定输出目录
                        .outputDir(outputRootDir)
                        // 开启swagger模式
                        .enableSwagger()
                )
                // 包配置
                .packageConfig(builder -> builder
                        // 指定生成的类的所属包
                        .parent(packagePath)
                        .entity("entity.po")
                        .service("service")
                        .serviceImpl("service.impl")
                        .mapper("mapper")
                        .xml("mapper")
                        .controller("controller")
                        .other("other"))
                // 策略配置
                .strategyConfig(builder -> builder
                        // => 表配置
                        // 设置需要生成代码的表名（不设置则全库生成） TODO
                        .addInclude(
                                "sys_aksk_user"
                        )
                        // 设置过滤表前缀
                        // .addTablePrefix("tmp_")
                        // 设置过滤表后缀
                        // .addTableSuffix("_tmp")
                        
                        // => entity配置
                        .entityBuilder()
                        .convertFileName((entityName) -> entityName + "PO")
                        /// 给po设置公共父类
                        ///.superClass(PoSupperEntity.class)
                        ///设置生成的PO里面的对应字段有填充标识或者逻辑删除标识
                        // 逻辑删除字段名
                        .logicDeletePropertyName("deleted")
                        // 自动填充
                        .addTableFills(new Property("createdBy", FieldFill.INSERT))
                        .addTableFills(new Property("createdAt", FieldFill.INSERT))
                        .addTableFills(new Property("updatedBy", FieldFill.INSERT_UPDATE))
                        .addTableFills(new Property("updatedAt", FieldFill.INSERT_UPDATE))
                        // 启用TableField等相关注解
                        .enableTableFieldAnnotation()
                        .enableLombok()
                        
                        // => controller配置
                        .controllerBuilder()
                        .enableRestStyle()
                        .convertFileName((entityName) -> entityName + "Controller")
                        // .superClass(BaseController.class)
                        
                        // => service配置
                        .serviceBuilder()
                        .convertServiceFileName((entityName) -> entityName + "Service")
                        .convertServiceImplFileName((entityName) -> entityName + "ServiceImpl")
                        
                        // => mapper配置
                        .mapperBuilder()
                        .enableMapperAnnotation()
                        .convertMapperFileName((entityName) -> entityName + "Mapper")
                        .convertXmlFileName((entityName) -> entityName + "Mapper"))
                .templateEngine(useCustomTemplate ? new EnhanceFreemarkerTemplateEngine() : new FreemarkerTemplateEngine());
        
        // entity、service、serviceImpl、controller、mapper、xml，使用指定模板生成
        fastAutoGenerator.templateConfig((TemplateConfig.Builder builder) -> {
            if (useCustomTemplate) {
                /*
                 * 使用自定义的模板
                 * 注：参考mybatis-plus-generator包下的默认模板进行编写即可
                 * 注：自定义的模板放在classpath下的对应位置即可
                 * 注：指定模板时，无需带对应的模板后缀名（如：这里不带.ftl）
                 */
                builder
                        .entity("/" + templateDir + "/" + "custom_entity")
                        .service("/" + templateDir + "/" + "custom_service")
                        .serviceImpl("/" + templateDir + "/" + "custom_serviceImpl")
                        .controller("/" + templateDir + "/" + "custom_controller")
                        // 不改的话，用默认的即可
                        .mapper(ConstVal.TEMPLATE_MAPPER)
                        .xml(ConstVal.TEMPLATE_XML);
            } else {
                // 使用mybatis-plus-generator包下的默认模板
                builder
                        .entity(ConstVal.TEMPLATE_ENTITY_JAVA)
                        .mapper(ConstVal.TEMPLATE_MAPPER)
                        .xml(ConstVal.TEMPLATE_XML)
                        .service(ConstVal.TEMPLATE_SERVICE)
                        .serviceImpl(ConstVal.TEMPLATE_SERVICE_IMPL)
                        .controller(ConstVal.TEMPLATE_CONTROLLER);
            }
        });
        
        fastAutoGenerator.execute();
    }
    
    /* --------------------------------------------------------------- 以下部分，可以不关心 --------------------------------------------------------------- */
    
    
    /**
     * 扩展FreemarkerTemplateEngine，生成更多相关文件
     */
    public static class EnhanceFreemarkerTemplateEngine extends FreemarkerTemplateEngine {
        
        /**
         * (non-javadoc)
         *
         * @param customFile
         *         自定义文件； key-生成的文件； value-生成该文件使用的（classpath下的带模板文件后缀名的）模板文件
         * @param tableInfo
         *         表信息
         * @param objectMap
         *         模板可使用的占位符即对应变量值(即：objectMap里的key可以在模板文件中直接引用)
         */
        @Override
        protected void outputCustomFile(@NonNull Map<String, String> customFile, @NonNull TableInfo tableInfo,
                                        @NonNull Map<String, Object> objectMap) {
            String entityName = tableInfo.getEntityName();
            String entityPath = this.getPathInfo(OutputFile.entity);
            String originEntityName;
            if (entityName.endsWith("PO")) {
                originEntityName = entityName.substring(0, entityName.length() - 2);
            } else {
                originEntityName = entityName;
            }
            // 自定义一些key-value，以便在模板中获取对应的值
            String comment = tableInfo.getComment();
            String originEntityNameHyphenStyle = StringUtils.camelToHyphen(originEntityName);
            objectMap.put("originEntityName", originEntityName);
            objectMap.put("customLowerServiceName", StringUtils.firstToLowerCase(tableInfo.getServiceName()));
            objectMap.put("originEntityNameHyphenStyle", originEntityNameHyphenStyle);
            objectMap.put("briefTableComment", StringUtils.isNotBlank(comment) ? comment.replace("表", "").trim() : originEntityNameHyphenStyle);
            objectMap.put("wrapControllerResult", wrapControllerResult);
            objectMap.put("ifAddExcelPropertyAnno", ifAddExcelPropertyAnno);
            Set<String> importPackages = tableInfo.getImportPackages();
            
            String superClassLongName;
            List<String> superClassImportList;
            try {
                Field entityField = TableInfo.class.getDeclaredField("entity");
                entityField.setAccessible(true);
                Entity entity = (Entity)entityField.get(tableInfo);
                superClassLongName = entity.getSuperClass();
                superClassImportList = Arrays.stream(Class.forName(superClassLongName).getDeclaredFields())
                        .map(field -> field.getType().getName())
                        .filter(x -> !x.startsWith("java.lang.")).collect(Collectors.toList());
            } catch (Exception e) {
                superClassLongName = null;
                superClassImportList = null;
                logger.warn(e.getMessage());
            }
            String finalSuperClassImport = superClassLongName;
            LinkedHashSet<String> importPackageList = new LinkedHashSet<>(importPackages);
            if (!CollectionUtils.isEmpty(superClassImportList)) {
                importPackageList.addAll(superClassImportList);
            }
            Set<String> customImportPackages = importPackageList.stream()
                    .filter(pack -> {
                        if ("java.io.Serializable".equals(pack)) {
                            return false;
                        }
                        if (pack.equals(finalSuperClassImport)) {
                            return false;
                        }
                        return !pack.startsWith("com.baomidou.");
                    }).collect(Collectors.toCollection(TreeSet::new));
            objectMap.put("customImportPackages", customImportPackages);
            
            List<TableField> customAllFields = new ArrayList<>(32);
            List<TableField> commonFields = tableInfo.getCommonFields();
            if (!CollectionUtils.isEmpty(commonFields)) {
                customAllFields.addAll(commonFields);
            }
            List<TableField> fields = tableInfo.getFields();
            if (!CollectionUtils.isEmpty(fields)) {
                customAllFields.addAll(fields);
            }
            objectMap.put("customAllFields", customAllFields);
            
            /// customFile.forEach((key, value) -> {
            ///     String fileName = String.format(entityPath + File.separator + entityName + "%s", key);
            ///     this.outputFile(new File(fileName), objectMap, value, true); 参数分别是：要生成的文件, 模板可以取的参数,
            // classpath下的模板文件(带模板文件后缀名), 是否覆盖已有文件
            /// });
            // 生成xxxAddReqVO
            this.outputFile(new File(entityPath + File.separator + "req" + File.separator + originEntityName +
                    "AddReqVO.java"), objectMap, "/" + templateDir + "/PojoAddReqVO.ftl", true);
            // 生成xxxUpdateReqVOentityPath + File.separator + "req" + File.separator + originEntityName + "AddReqVO
            // .java" = "E:/Git/Repository/part-time-job/pension-platform-java/pension-basic/src/test/java/\com
            // \ideaaedi\smart\pension\basic\mybatisPlus\generator\entity\po\req\CmMonitorInfoAddReqVO.java"
            this.outputFile(new File(entityPath + File.separator + "req" + File.separator + originEntityName +
                    "UpdateReqVO.java"), objectMap, "/" + templateDir + "/PojoUpdateReqVO.ftl", true);
            // 生成xxxListReqVO
            this.outputFile(new File(entityPath + File.separator + "req" + File.separator + originEntityName +
                    "ListReqVO.java"), objectMap, "/" + templateDir + "/PojoListReqVO.ftl", true);
            // 生成xxxBatchAddReqVO
            this.outputFile(new File(entityPath + File.separator + "req" + File.separator + originEntityName +
                            "BatchAddReqVO.java"), objectMap, "/" + templateDir + "/PojoBatchAddReqVO.ftl",
                    true);
            // 生成xxxListRespVO
            this.outputFile(new File(entityPath + File.separator + "resp" + File.separator + originEntityName +
                    "ListRespVO.java"), objectMap, "/" + templateDir + "/PojoListRespVO.ftl", true);
            // 生成xxxDetailRespVO
            this.outputFile(new File(entityPath + File.separator + "resp" + File.separator + originEntityName +
                            "DetailRespVO.java"), objectMap, "/" + templateDir + "/PojoDetailRespVO.ftl",
                    true);
            // 生成xxxDBatchAddRespVO
            this.outputFile(new File(entityPath + File.separator + "resp" + File.separator + originEntityName +
                            "BatchAddRespVO.java"), objectMap, "/" + templateDir + "/PojoBatchAddRespVO.ftl",
                    true);
        }
    }
    
    /**
     * 自定义的模板
     */
    @Getter
    @SuppressWarnings("FieldCanBeLocal")
    public enum JustryDengTemplates {
        custom_controller("custom_controller.ftl", "package ${package.Controller};\n"
                + "\n"
                + "import ${package.Entity}.req.${originEntityName}AddReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}BatchAddReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}ListReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}UpdateReqVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}BatchAddRespVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}DetailRespVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}ListRespVO;\n"
                + "import ${package.Service}.${table.serviceName};\n"
                + "import JustryDeng_Placeholder.PageInfo;\n"
                + "<#if wrapControllerResult>\n"
                + "import JustryDeng_Placeholder.Result;\n"
                + "</#if>\n"
                + "<#if superControllerClassPackage??>\n"
                + "import ${superControllerClassPackage};\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.Api;\n"
                + "import io.swagger.annotations.ApiOperation;\n"
                + "import io.swagger.annotations.ApiParam;\n"
                + "</#if>\n"
                + "import org.springframework.validation.annotation.Validated;\n"
                + "import org.springframework.web.bind.annotation.DeleteMapping;\n"
                + "import org.springframework.web.bind.annotation.GetMapping;\n"
                + "import org.springframework.web.bind.annotation.PathVariable;\n"
                + "import org.springframework.web.bind.annotation.PostMapping;\n"
                + "import org.springframework.web.bind.annotation.PutMapping;\n"
                + "import org.springframework.web.bind.annotation.RequestBody;\n"
                + "import org.springframework.web.bind.annotation.RequestMapping;\n"
                + "<#if restControllerStyle>\n"
                + "import org.springframework.web.bind.annotation.RestController;\n"
                + "<#else>\n"
                + "import org.springframework.stereotype.Controller;\n"
                + "</#if>\n"
                + "\n"
                + "import javax.annotation.Resource;\n"
                + "import javax.validation.constraints.NotNull;\n"
                + "\n"
                + "/**\n"
                + " * ${briefTableComment}\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "@Validated\n"
                + "<#if restControllerStyle>\n"
                + "@RestController\n"
                + "<#else>\n"
                + "@Controller\n"
                + "</#if>\n"
                + "@RequestMapping(\"<#if package.ModuleName?? && package.ModuleName != \"\">/${package"
                + ".ModuleName}</#if>/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>$"
                + "{originEntityNameHyphenStyle}</#if>\")\n"
                + "<#if swagger>\n"
                + "@Api(value = \"${briefTableComment}\", tags = {\"${briefTableComment}\"})\n"
                + "</#if>\n"
                + "<#if kotlin>\n"
                + "class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>\n"
                + "<#else>\n"
                + "<#if superControllerClass??>\n"
                + "public class ${table.controllerName} extends ${superControllerClass} {\n"
                + "<#else>\n"
                + "public class ${table.controllerName} {\n"
                + "</#if>\n"
                + "\n"
                + "    @Resource\n"
                + "    private ${table.serviceName} ${customLowerServiceName};\n"
                + "\n"
                + "    /**\n"
                + "     * 增\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return 新增的数据详情\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiOperation(\"增\")\n"
                + "    </#if>\n"
                + "    @PostMapping(\"/add\")\n"
                + "    public <#if wrapControllerResult>Result<</#if>${originEntityName}DetailRespVO<#if "
                + "wrapControllerResult>></#if> add(@RequestBody @Validated ${originEntityName}AddReqVO req) {\n"
                + "        return <#if wrapControllerResult>Result.success(</#if>${customLowerServiceName}.add(req, "
                + "true)<#if wrapControllerResult>)</#if>;\n"
                + "    }\n"
                + "\n"
                + "    /**\n"
                + "     * 批量增\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return ${originEntityName}BatchAddRespVO\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiOperation(\"批量增\")\n"
                + "    </#if>\n"
                + "    @PostMapping(\"/batch-add\")\n"
                + "    public <#if wrapControllerResult>Result<</#if>${originEntityName}BatchAddRespVO<#if "
                + "wrapControllerResult>></#if> batchAdd(@RequestBody @Validated ${originEntityName}BatchAddReqVO "
                + "req) {\n"
                + "        return <#if wrapControllerResult>Result.success(</#if>${customLowerServiceName}.batchAdd"
                + "(req)<#if wrapControllerResult>)</#if>;\n"
                + "    }\n"
                + "\n"
                + "    /**\n"
                + "     * 删\n"
                + "     *\n"
                + "     * @param id 要删除数据的id\n"
                + "     *\n"
                + "     * @return 删除了的数据详情\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiOperation(\"删\")\n"
                + "    </#if>\n"
                + "    @DeleteMapping(\"/delete/{id}\")\n"
                + "    public <#if wrapControllerResult>Result<</#if>${originEntityName}DetailRespVO<#if "
                + "wrapControllerResult>></#if> delete(<#if swagger>@ApiParam(value = \"要删除数据的id\", required = true)\n"
                + "                                            </#if>@PathVariable(\"id\") @NotNull(message = \"id "
                + "cannot be null.\") <#list customAllFields as field><#if field.keyFlag>${field"
                + ".propertyType}</#if></#list> id) {\n"
                + "        return <#if wrapControllerResult>Result.success(</#if>${customLowerServiceName}.delete(id)"
                + "<#if wrapControllerResult>)</#if>;\n"
                + "    }\n"
                + "\n"
                + "    /**\n"
                + "     * 改\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return 修改后的数据详情\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiOperation(\"改\")\n"
                + "    </#if>\n"
                + "    @PutMapping(\"/update\")\n"
                + "    public <#if wrapControllerResult>Result<</#if>${originEntityName}DetailRespVO<#if "
                + "wrapControllerResult>></#if> update(@RequestBody @Validated ${originEntityName}UpdateReqVO req) {\n"
                + "        return <#if wrapControllerResult>Result.success(</#if>${customLowerServiceName}.update"
                + "(req)<#if wrapControllerResult>)</#if>;\n"
                + "    }\n"
                + "\n"
                + "    /**\n"
                + "     * 查详情\n"
                + "     *\n"
                + "     * @param id 要查询数据的id\n"
                + "     *\n"
                + "     * @return 数据详情\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiOperation(\"查详情\")\n"
                + "    </#if>\n"
                + "    @GetMapping(\"/detail/{id}\")\n"
                + "    public <#if wrapControllerResult>Result<</#if>${originEntityName}DetailRespVO<#if "
                + "wrapControllerResult>></#if> detail(<#if swagger>@ApiParam(value = \"要查询数据的id\", required = true)\n"
                + "                                            </#if>@PathVariable(\"id\") @NotNull(message = \"id "
                + "cannot be null.\") <#list customAllFields as field><#if field.keyFlag>${field"
                + ".propertyType}</#if></#list> id) {\n"
                + "        return <#if wrapControllerResult>Result.success(</#if>${customLowerServiceName}.detail(id)"
                + "<#if wrapControllerResult>)</#if>;\n"
                + "    }\n"
                + "\n"
                + "    /**\n"
                + "     * 查列表\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return 数据列表\n"
                + "     */\n"
                + "    @PostMapping(\"/list\")\n"
                + "    <#if swagger>\n"
                + "    @ApiOperation(\"查列表\")\n"
                + "    </#if>\n"
                + "    public <#if wrapControllerResult>Result<</#if>PageInfo<${originEntityName}ListRespVO><#if "
                + "wrapControllerResult>></#if> list(@RequestBody @Validated ${originEntityName}ListReqVO req) {\n"
                + "        return <#if wrapControllerResult>Result.success(</#if>${customLowerServiceName}.list(req)"
                + "<#if wrapControllerResult>)</#if>;\n"
                + "    }\n"
                + "\n"
                + "}\n"
                + "</#if>"),
        custom_entity("custom_entity.ftl", "package ${package.Entity};\n"
                + "\n"
                + "<#list table.importPackages as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "    <#if superEntityClass??>\n"
                + "import lombok.EqualsAndHashCode;\n"
                + "    </#if>\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} po模型\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "    <#if superEntityClass??>\n"
                + "@EqualsAndHashCode(callSuper = true)\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "<#if table.convert>\n"
                + "@TableName(\"${schemaName}${table.name}\")\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!}\")\n"
                + "</#if>\n"
                + "<#if superEntityClass??>\n"
                + "public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> implements "
                + "Serializable {\n"
                + "<#elseif activeRecord>\n"
                + "public class ${entity} extends Model<${entity}> implements Serializable {\n"
                + "<#elseif entitySerialVersionUID>\n"
                + "public class ${entity} implements Serializable {\n"
                + "<#else>\n"
                + "public class ${entity} {\n"
                + "</#if>\n"
                + "<#if entitySerialVersionUID>\n"
                + "\n"
                + "    private static final long serialVersionUID = 1L;\n"
                + "</#if>\n"
                + "<#-- ----------  BEGIN 字段循环遍历  ---------->\n"
                + "<#list table.fields as field>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#assign keyPropertyName=\"${field.propertyName}\"/>\n"
                + "    </#if>\n"
                + "\n"
                + "    <#if field.comment!?length gt 0>\n"
                + "        <#if swagger>\n"
                + "    @ApiModelProperty(\"${field.comment}\")\n"
                + "        <#else>\n"
                + "    /**\n"
                + "     * ${field.comment}\n"
                + "     */\n"
                + "        </#if>\n"
                + "    </#if>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#-- 主键 -->\n"
                + "        <#if field.keyIdentityFlag>\n"
                + "    @TableId(value = \"${field.annotationColumnName}\", type = IdType.AUTO)\n"
                + "        <#elseif idType??>\n"
                + "    @TableId(value = \"${field.annotationColumnName}\", type = IdType.${idType})\n"
                + "        <#elseif field.convert>\n"
                + "    @TableId(\"${field.annotationColumnName}\")\n"
                + "        </#if>\n"
                + "        <#-- 普通字段 -->\n"
                + "    <#elseif field.fill??>\n"
                + "    <#-- -----   存在字段填充设置   ----->\n"
                + "        <#if field.convert>\n"
                + "    @TableField(value = \"${field.annotationColumnName}\", fill = FieldFill.${field.fill})\n"
                + "        <#else>\n"
                + "    @TableField(fill = FieldFill.${field.fill})\n"
                + "        </#if>\n"
                + "    <#elseif field.convert>\n"
                + "    @TableField(\"${field.annotationColumnName}\")\n"
                + "    </#if>\n"
                + "    <#-- 乐观锁注解 -->\n"
                + "    <#if field.versionField>\n"
                + "    @Version\n"
                + "    </#if>\n"
                + "    <#-- 逻辑删除注解 -->\n"
                + "    <#if field.logicDeleteField>\n"
                + "    @TableLogic\n"
                + "    </#if>\n"
                + "    private ${field.propertyType} ${field.propertyName};\n"
                + "</#list>\n"
                + "<#------------  END 字段循环遍历  ---------->\n"
                + "\n"
                + "<#if !entityLombokModel>\n"
                + "    <#list table.fields as field>\n"
                + "        <#if field.propertyType == \"boolean\">\n"
                + "            <#assign getprefix=\"is\"/>\n"
                + "        <#else>\n"
                + "            <#assign getprefix=\"get\"/>\n"
                + "        </#if>\n"
                + "    public ${field.propertyType} ${getprefix}${field.capitalName}() {\n"
                + "        return ${field.propertyName};\n"
                + "    }\n"
                + "\n"
                + "    <#if chainModel>\n"
                + "    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    <#else>\n"
                + "    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    </#if>\n"
                + "        this.${field.propertyName} = ${field.propertyName};\n"
                + "        <#if chainModel>\n"
                + "        return this;\n"
                + "        </#if>\n"
                + "    }\n"
                + "    </#list>\n"
                + "\n"
                + "</#if>\n"
                + "<#if entityColumnConstant>\n"
                + "    <#list table.fields as field>\n"
                + "    public static final String ${field.name?upper_case} = \"${field.name}\";\n"
                + "\n"
                + "    </#list>\n"
                + "\n"
                + "</#if>\n"
                + "<#if activeRecord>\n"
                + "    @Override\n"
                + "    public Serializable pkVal() {\n"
                + "    <#if keyPropertyName??>\n"
                + "        return this.${keyPropertyName};\n"
                + "    <#else>\n"
                + "        return null;\n"
                + "    </#if>\n"
                + "    }\n"
                + "\n"
                + "</#if>\n"
                + "<#if !entityLombokModel>\n"
                + "    @Override\n"
                + "    public String toString() {\n"
                + "        return \"${entity}{\" +\n"
                + "    <#list table.fields as field>\n"
                + "        <#if field_index==0>\n"
                + "            \"${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        <#else>\n"
                + "            \", ${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        </#if>\n"
                + "    </#list>\n"
                + "        \"}\";\n"
                + "    }\n"
                + "\n"
                + "</#if>\n"
                + "}"),
        custom_service("custom_service.ftl", "package ${package.Service};\n"
                + "\n"
                + "import ${superServiceClassPackage};\n"
                + "import ${package.Entity}.${entity};\n"
                + "import ${package.Entity}.req.${originEntityName}AddReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}BatchAddReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}ListReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}UpdateReqVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}BatchAddRespVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}DetailRespVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}ListRespVO;\n"
                + "import JustryDeng_Placeholder.PageInfo;\n"
                + "import org.springframework.lang.Nullable;\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${briefTableComment} 服务类\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if kotlin>\n"
                + "interface ${table.serviceName} : ${superServiceClass}<${entity}>\n"
                + "<#else>\n"
                + "public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {\n"
                + "\n"
                + "    /**\n"
                + "     * 增\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     * @param queryDetail true-查询并返回详情; false-返回null\n"
                + "     *\n"
                + "     * @return 新增的数据详情（当queryDetail为true时，返回null）\n"
                + "     */\n"
                + "    @Nullable\n"
                + "    ${originEntityName}DetailRespVO add(${originEntityName}AddReqVO req, boolean queryDetail);\n"
                + "\n"
                + "    /**\n"
                + "     * 批量增\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return 批量新增结果\n"
                + "     */\n"
                + "    ${originEntityName}BatchAddRespVO batchAdd(${originEntityName}BatchAddReqVO req);\n"
                + "\n"
                + "    /**\n"
                + "     * 删\n"
                + "     *\n"
                + "     * @param id 要删除数据的id\n"
                + "     *\n"
                + "     * @return 删除了的数据详情\n"
                + "     */\n"
                + "    ${originEntityName}DetailRespVO delete(<#list customAllFields as field><#if field"
                + ".keyFlag>${field.propertyType}</#if></#list> id);\n"
                + "\n"
                + "    /**\n"
                + "     * 改\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return 修改后的数据详情\n"
                + "     */\n"
                + "    @Nullable\n"
                + "    ${originEntityName}DetailRespVO update(${originEntityName}UpdateReqVO req);\n"
                + "\n"
                + "    /**\n"
                + "     * 查详情\n"
                + "     *\n"
                + "     * @param id 要查询数据的id\n"
                + "     *\n"
                + "     * @return 数据详情\n"
                + "     */\n"
                + "    @Nullable\n"
                + "    ${originEntityName}DetailRespVO detail(<#list customAllFields as field><#if field"
                + ".keyFlag>${field.propertyType}</#if></#list> id);\n"
                + "\n"
                + "    /**\n"
                + "     * 查列表\n"
                + "     *\n"
                + "     * @param req 参数\n"
                + "     *\n"
                + "     * @return 数据列表\n"
                + "     */\n"
                + "    PageInfo<${originEntityName}ListRespVO> list(${originEntityName}ListReqVO req);\n"
                + "}\n"
                + "</#if>"),
        custom_serviceImpl("custom_serviceImpl.ftl", "package ${package.ServiceImpl};\n"
                + "\n"
                + "import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;\n"
                + "import com.baomidou.mybatisplus.core.metadata.IPage;\n"
                + "        <#list customAllFields as field>\n"
                + "            <#if field.keyFlag>\n"
                + "        <#-- 自增主键, 不需要导入IdWorker -->\n"
                + "                <#if field.keyIdentityFlag>\n"
                + "                <#else>\n"
                + "        <#-- 其它类型的主键（这里统一认为是雪花算法生成的id） -->\n"
                + "import com.baomidou.mybatisplus.core.toolkit.IdWorker;\n"
                + "                </#if>\n"
                + "            </#if>\n"
                + "        </#list>\n"
                + "import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n"
                + "import ${superServiceImplClassPackage};\n"
                + "import ${package.Entity}.${entity};\n"
                + "import ${package.Entity}.req.${originEntityName}AddReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}BatchAddReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}ListReqVO;\n"
                + "import ${package.Entity}.req.${originEntityName}UpdateReqVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}BatchAddRespVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}DetailRespVO;\n"
                + "import ${package.Entity}.resp.${originEntityName}ListRespVO;\n"
                + "import ${package.Mapper}.${table.mapperName};\n"
                + "import ${package.Service}.${table.serviceName};\n"
                + "import JustryDeng_Placeholder.PageInfo;\n"
                + "import org.springframework.aop.framework.AopContext;\n"
                + "import org.springframework.beans.BeanUtils;\n"
                + "import org.springframework.lang.Nullable;\n"
                + "import org.springframework.stereotype.Service;\n"
                + "import org.springframework.transaction.annotation.Transactional;\n"
                + "import org.springframework.util.CollectionUtils;\n"
                + "\n"
                + "<#list customImportPackages! as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "import java.util.Collections;\n"
                + "import java.util.List;\n"
                + "import java.util.Objects;\n"
                + "import java.util.stream.Collectors;\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${briefTableComment} 服务实现类\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "@Service\n"
                + "<#if kotlin>\n"
                + "open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), "
                + "${table.serviceName} {\n"
                + "\n"
                + "}\n"
                + "<#else>\n"
                + "public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, "
                + "${entity}> implements ${table.serviceName} {\n"
                + "\n"
                + "    @Nullable\n"
                + "    @Override\n"
                + "    @Transactional(rollbackFor = Exception.class)\n"
                + "    public ${originEntityName}DetailRespVO add(${originEntityName}AddReqVO req, boolean "
                + "queryDetail) {\n"
                + "        ${entity} po = new ${entity}();\n"
                + "        BeanUtils.copyProperties(req, po);\n"
                + "        <#list customAllFields as field>\n"
                + "            <#if field.propertyType == \"boolean\">\n"
                + "                <#assign getprefix=\"is\"/>\n"
                + "            <#else>\n"
                + "                <#assign getprefix=\"get\"/>\n"
                + "            </#if>\n"
                + "            <#if field.keyFlag>\n"
                + "        <#-- 自增主键 -->\n"
                + "                <#if field.keyIdentityFlag>\n"
                + "        po.set${field.capitalName}(null);\n"
                + "        save(po);\n"
                + "        return queryDetail ? detail(po.${getprefix}${field.capitalName}()) : null;\n"
                + "                <#else>\n"
                + "        <#-- 其它类型的主键（这里统一认为是雪花算法生成的id） -->\n"
                + "        long id = IdWorker.getId();\n"
                + "        po.set${field.capitalName}(id);\n"
                + "        save(po);\n"
                + "        return queryDetail ? detail(id) : null;\n"
                + "                </#if>\n"
                + "            </#if>\n"
                + "        </#list>\n"
                + "    }\n"
                + "\n"
                + "    @Override\n"
                + "    public ${originEntityName}BatchAddRespVO batchAdd(${originEntityName}BatchAddReqVO req) {\n"
                + "        Boolean ifOneByOne = req.getIfOneByOne();\n"
                + "        Objects.requireNonNull(ifOneByOne, \"ifOneByOne cannot be null.\");\n"
                + "        List<${originEntityName}BatchAddReqVO.AddItemParamDTO> dataList = req.getDataList();\n"
                + "        ${table.serviceName} thisService = (${table.serviceName}) AopContext.currentProxy();\n"
                + "        if (ifOneByOne) {\n"
                + "            for (${originEntityName}BatchAddReqVO.AddItemParamDTO item : dataList) {\n"
                + "                try {\n"
                + "                    thisService.add(item, false);\n"
                + "                    item.setResult(true);\n"
                + "                } catch (Exception e) {\n"
                + "                    item.setResult(false);\n"
                + "                    item.setFailInfo(e.getMessage());\n"
                + "                }\n"
                + "            }\n"
                + "        } else {\n"
                + "            // 出于性能及业务差异考虑, 这里不直接生成. 需要的话，请自己实现\n"
                + "            throw new UnsupportedOperationException(\"Un-support ifOneByOne is false.\");\n"
                + "        }\n"
                + "        ${originEntityName}BatchAddRespVO resp = new ${originEntityName}BatchAddRespVO();\n"
                + "        resp.setDataList(dataList);\n"
                + "        resp.setIfAllSuccess(dataList.stream().allMatch(x -> x.getResult() != null && x.getResult"
                + "()));\n"
                + "        return resp;\n"
                + "    }\n"
                + "\n"
                + "    @Override\n"
                + "    @Transactional(rollbackFor = Exception.class)\n"
                + "    public ${originEntityName}DetailRespVO delete(<#list customAllFields as field><#if field"
                + ".keyFlag>${field.propertyType}</#if></#list> id) {\n"
                + "        Objects.requireNonNull(id, \"id cannot be null.\");\n"
                + "        ${originEntityName}DetailRespVO resp = detail(id);\n"
                + "        removeById(id);\n"
                + "        return resp;\n"
                + "    }\n"
                + "\n"
                + "    @Nullable\n"
                + "    @Override\n"
                + "    @Transactional(rollbackFor = Exception.class)\n"
                + "    public ${originEntityName}DetailRespVO update(${originEntityName}UpdateReqVO req) {\n"
                + "        <#list customAllFields as field>\n"
                + "            <#if field.keyFlag>\n"
                + "                <#if field.propertyType == \"boolean\">\n"
                + "                    <#assign getprefix=\"is\"/>\n"
                + "                <#else>\n"
                + "                    <#assign getprefix=\"get\"/>\n"
                + "                </#if>\n"
                + "        ${field.propertyType} id = req.${getprefix}${field.capitalName}();\n"
                + "            </#if>\n"
                + "        </#list>\n"
                + "        Objects.requireNonNull(id, \"id cannot be null.\");\n"
                + "        // mybatis-plus默认的updateById方法，更新策略默认是NOT_NULL（即更新数据时数据为NULL值时将不更新进数据库）\n"
                + "        ${entity} po = new ${entity}();\n"
                + "        BeanUtils.copyProperties(req, po);\n"
                + "        updateById(po);\n"
                + "        return detail(id);\n"
                + "    }\n"
                + "\n"
                + "    @Nullable\n"
                + "    @Override\n"
                + "    public ${originEntityName}DetailRespVO detail(<#list customAllFields as field><#if field"
                + ".keyFlag>${field.propertyType}</#if></#list> id) {\n"
                + "        Objects.requireNonNull(id, \"id cannot be null.\");\n"
                + "        ${entity} po = getById(id);\n"
                + "        if (po == null) {\n"
                + "            return null;\n"
                + "        }\n"
                + "        ${originEntityName}DetailRespVO resp = new ${originEntityName}DetailRespVO();\n"
                + "        BeanUtils.copyProperties(po, resp);\n"
                + "        return resp;\n"
                + "    }\n"
                + "    \n"
                + "    @Override\n"
                + "    public PageInfo<${originEntityName}ListRespVO> list(${originEntityName}ListReqVO req) {\n"
                + "        int pageNum = req.getPageNum();\n"
                + "        int pageSize = req.getPageSize();\n"
                + "        <#list customAllFields as field>\n"
                + "            <#if field.propertyType == \"boolean\">\n"
                + "                <#assign getprefix=\"is\"/>\n"
                + "            <#else>\n"
                + "                <#assign getprefix=\"get\"/>\n"
                + "            </#if>\n"
                + "        ${field.propertyType} ${field.propertyName} = req.${getprefix}${field.capitalName}();\n"
                + "        </#list>\n"
                + "\n"
                + "        // 分页查\n"
                + "        IPage<${entity}> pageInfo = new Page<>(pageNum, pageSize);\n"
                + "        IPage<${entity}> page = this.baseMapper.selectPage(pageInfo,\n"
                + "                new LambdaQueryWrapper<${entity}>()\n"
                + "        <#list customAllFields as field>\n"
                + "            <#if field.propertyType == \"boolean\">\n"
                + "                <#assign getprefix=\"is\"/>\n"
                + "            <#else>\n"
                + "                <#assign getprefix=\"get\"/>\n"
                + "            </#if>\n"
                + "            .eq(<#if field.propertyType == \"String\">${field.propertyName} != null && ${field"
                + ".propertyName}.trim().length() != 0<#else>${field.propertyName} != null</#if>,  "
                + "${entity}::${getprefix}${field.capitalName}, ${field.propertyName})\n"
                + "        </#list>\n"
                + "            .orderByDesc(${entity}::getId)\n"
                + "        );\n"
                + "        // 转换为resp模型\n"
                + "        List<${entity}> records = page.getRecords();\n"
                + "        List<${originEntityName}ListRespVO> list;\n"
                + "        if (CollectionUtils.isEmpty(records)) {\n"
                + "            list = Collections.emptyList();\n"
                + "        } else {\n"
                + "            list = records.stream().map(po -> {\n"
                + "                ${originEntityName}ListRespVO resp = new ${originEntityName}ListRespVO();\n"
                + "                BeanUtils.copyProperties(po, resp);\n"
                + "                return resp;\n"
                + "            }).collect(Collectors.toList());\n"
                + "        }\n"
                + "        return PageInfo.of(page.getTotal(), pageNum, pageSize, list);\n"
                + "    }\n"
                + "}\n"
                + "</#if>"),
        PojoAddReqVO("PojoAddReqVO.ftl", "package ${package.Entity}.req;\n"
                + "\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "import lombok.EqualsAndHashCode;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "import JustryDeng_Placeholder.BaseDTO;\n"
                + "\n"
                + "<#list customImportPackages! as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} add req\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "@EqualsAndHashCode(callSuper = true)\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} add req\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}AddReqVO extends BaseDTO {\n"
                + "<#-- ----------  BEGIN 字段循环遍历  ---------->\n"
                + "<#list customAllFields as field>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#assign keyPropertyName=\"${field.propertyName}\"/>\n"
                + "    </#if>\n"
                + "\n"
                + "    <#if field.comment!?length gt 0>\n"
                + "    /**\n"
                + "     * ${field.comment}\n"
                + "     */\n"
                + "        <#if swagger>\n"
                + "    @ApiModelProperty(\"${field.comment}\")\n"
                + "        </#if>\n"
                + "    </#if>\n"
                + "    private ${field.propertyType} ${field.propertyName};\n"
                + "</#list>\n"
                + "<#------------  END 字段循环遍历  ---------->\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field.propertyType == \"boolean\">\n"
                + "            <#assign getprefix=\"is\"/>\n"
                + "        <#else>\n"
                + "            <#assign getprefix=\"get\"/>\n"
                + "        </#if>\n"
                + "    public ${field.propertyType} ${getprefix}${field.capitalName}() {\n"
                + "        return ${field.propertyName};\n"
                + "    }\n"
                + "\n"
                + "    <#if chainModel>\n"
                + "    public ${originEntityName} set${field.capitalName}(${field.propertyType} ${field"
                + ".propertyName}) {\n"
                + "    <#else>\n"
                + "    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    </#if>\n"
                + "        this.${field.propertyName} = ${field.propertyName};\n"
                + "        <#if chainModel>\n"
                + "        return this;\n"
                + "        </#if>\n"
                + "    }\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "\n"
                + "<#if entityColumnConstant>\n"
                + "    <#list customAllFields as field>\n"
                + "    public static final String ${field.name?upper_case} = \"${field.name}\";\n"
                + "\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "<#if activeRecord>\n"
                + "    @Override\n"
                + "    public Serializable pkVal() {\n"
                + "    <#if keyPropertyName??>\n"
                + "        return this.${keyPropertyName};\n"
                + "    <#else>\n"
                + "        return null;\n"
                + "    </#if>\n"
                + "    }\n"
                + "</#if>\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    @Override\n"
                + "    public String toString() {\n"
                + "        return \"${originEntityName}{\" +\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field_index==0>\n"
                + "            \"${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        <#else>\n"
                + "            \", ${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        </#if>\n"
                + "    </#list>\n"
                + "        \"}\";\n"
                + "    }\n"
                + "</#if>\n"
                + "}"),
        PojoBatchAddReqVO("PojoBatchAddReqVO.ftl", "package ${package.Entity}.req;\n"
                + "\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "import lombok.EqualsAndHashCode;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "import JustryDeng_Placeholder.BaseDTO;\n"
                + "\n"
                + "import javax.validation.Valid;\n"
                + "import javax.validation.constraints.NotNull;\n"
                + "import javax.validation.constraints.Size;\n"
                + "import java.util.List;\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} batch-add resp\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "@EqualsAndHashCode(callSuper = true)\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} batch add resp\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}BatchAddReqVO extends BaseDTO {\n"
                + "\n"
                + "    /**\n"
                + "     * 是否逐个处理\n"
                + "     */\n"
                + "    @NotNull(message = \"ifOneByOne cannot be null\")\n"
                + "    <#if swagger>\n"
                + "    @ApiModelProperty(\"是否逐个处理(true-逐个处理, 其中失败的不影响成功的; false-统一处理, 要么全成功，要么全失败)\")\n"
                + "    </#if>\n"
                + "    private Boolean ifOneByOne;\n"
                + "\n"
                + "    /**\n"
                + "     * 数据集\n"
                + "     */\n"
                + "    @Valid\n"
                + "    <#if swagger>\n"
                + "    @ApiModelProperty(\"数据集\")\n"
                + "    </#if>\n"
                + "    @NotNull(message = \"reqList cannot be null\")\n"
                + "    @Size(min = 1, message = \"reqList cannot be empty\")\n"
                + "    private List<AddItemParamDTO> dataList;\n"
                + "\n"
                + "    /**\n"
                + "    * @see ${originEntityName}AddReqVO\n"
                + "    */\n"
                + "    @Data\n"
                + "    @EqualsAndHashCode(callSuper = true)\n"
                + "    public static class AddItemParamDTO extends ${originEntityName}AddReqVO {\n"
                + "\n"
                + "        /**\n"
                + "         * 是否成功\n"
                + "         */\n"
                + "        <#if swagger>\n"
                + "        @ApiModelProperty(\"是否成功\")\n"
                + "        </#if>\n"
                + "        private Boolean result;\n"
                + "\n"
                + "        /**\n"
                + "         * 失败原因\n"
                + "         */\n"
                + "        <#if swagger>\n"
                + "        @ApiModelProperty(\"失败原因\")\n"
                + "        </#if>\n"
                + "        private String failInfo;\n"
                + "    }\n"
                + "}"),
        PojoBatchAddRespVO("PojoBatchAddRespVO.ftl", "package ${package.Entity}.resp;\n"
                + "\n"
                + "import ${package.Entity}.req.${originEntityName}BatchAddReqVO;\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "\n"
                + "import java.util.List;\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} batch-add resp\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} batch add resp\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}BatchAddRespVO {\n"
                + "\n"
                + "    /**\n"
                + "     * 是否全部成功(true-全部成功; false-全部失败或部分失败)\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiModelProperty(\"是否全部成功(true-全部成功; false-全部失败或部分失败)\")\n"
                + "    </#if>\n"
                + "    private Boolean ifAllSuccess;\n"
                + "\n"
                + "    /**\n"
                + "     * 数据集\n"
                + "     */\n"
                + "    <#if swagger>\n"
                + "    @ApiModelProperty(\"数据集\")\n"
                + "    </#if>\n"
                + "    private List<${originEntityName}BatchAddReqVO.AddItemParamDTO> dataList;\n"
                + "}"),
        PojoDetailRespVO("PojoDetailRespVO.ftl", "package ${package.Entity}.resp;\n"
                + "\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "\n"
                + "<#list customImportPackages! as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} detail resp\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} detail resp\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}DetailRespVO {\n"
                + "<#-- ----------  BEGIN 字段循环遍历  ---------->\n"
                + "<#list customAllFields as field>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#assign keyPropertyName=\"${field.propertyName}\"/>\n"
                + "    </#if>\n"
                + "\n"
                + "    <#if field.comment!?length gt 0>\n"
                + "    /**\n"
                + "     * ${field.comment}\n"
                + "     */\n"
                + "        <#if swagger>\n"
                + "    @ApiModelProperty(\"${field.comment}\")\n"
                + "        </#if>\n"
                + "    </#if>\n"
                + "    private ${field.propertyType} ${field.propertyName};\n"
                + "</#list>\n"
                + "<#------------  END 字段循环遍历  ---------->\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field.propertyType == \"boolean\">\n"
                + "            <#assign getprefix=\"is\"/>\n"
                + "        <#else>\n"
                + "            <#assign getprefix=\"get\"/>\n"
                + "        </#if>\n"
                + "    public ${field.propertyType} ${getprefix}${field.capitalName}() {\n"
                + "        return ${field.propertyName};\n"
                + "    }\n"
                + "\n"
                + "    <#if chainModel>\n"
                + "    public ${originEntityName} set${field.capitalName}(${field.propertyType} ${field"
                + ".propertyName}) {\n"
                + "    <#else>\n"
                + "    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    </#if>\n"
                + "        this.${field.propertyName} = ${field.propertyName};\n"
                + "        <#if chainModel>\n"
                + "        return this;\n"
                + "        </#if>\n"
                + "    }\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "\n"
                + "<#if entityColumnConstant>\n"
                + "    <#list customAllFields as field>\n"
                + "    public static final String ${field.name?upper_case} = \"${field.name}\";\n"
                + "\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "<#if activeRecord>\n"
                + "    @Override\n"
                + "    public Serializable pkVal() {\n"
                + "    <#if keyPropertyName??>\n"
                + "        return this.${keyPropertyName};\n"
                + "    <#else>\n"
                + "        return null;\n"
                + "    </#if>\n"
                + "    }\n"
                + "</#if>\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    @Override\n"
                + "    public String toString() {\n"
                + "        return \"${originEntityName}{\" +\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field_index==0>\n"
                + "            \"${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        <#else>\n"
                + "            \", ${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        </#if>\n"
                + "    </#list>\n"
                + "        \"}\";\n"
                + "    }\n"
                + "</#if>\n"
                + "}"),
        PojoListReqVO("PojoListReqVO.ftl", "package ${package.Entity}.req;\n"
                + "\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "import lombok.EqualsAndHashCode;\n"
                + "import JustryDeng_Placeholder.BasePageDTO;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "\n"
                + "<#list customImportPackages! as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} list req\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "@EqualsAndHashCode(callSuper = true)\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} list req\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}ListReqVO extends BasePageDTO {\n"
                + "<#-- ----------  BEGIN 字段循环遍历  ---------->\n"
                + "<#list customAllFields as field>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#assign keyPropertyName=\"${field.propertyName}\"/>\n"
                + "    </#if>\n"
                + "\n"
                + "    <#if field.comment!?length gt 0>\n"
                + "    /**\n"
                + "     * ${field.comment}\n"
                + "     */\n"
                + "        <#if swagger>\n"
                + "    @ApiModelProperty(\"${field.comment}\")\n"
                + "        </#if>\n"
                + "    </#if>\n"
                + "    private ${field.propertyType} ${field.propertyName};\n"
                + "</#list>\n"
                + "<#------------  END 字段循环遍历  ---------->\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field.propertyType == \"boolean\">\n"
                + "            <#assign getprefix=\"is\"/>\n"
                + "        <#else>\n"
                + "            <#assign getprefix=\"get\"/>\n"
                + "        </#if>\n"
                + "    public ${field.propertyType} ${getprefix}${field.capitalName}() {\n"
                + "        return ${field.propertyName};\n"
                + "    }\n"
                + "\n"
                + "    <#if chainModel>\n"
                + "    public ${originEntityName} set${field.capitalName}(${field.propertyType} ${field"
                + ".propertyName}) {\n"
                + "    <#else>\n"
                + "    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    </#if>\n"
                + "        this.${field.propertyName} = ${field.propertyName};\n"
                + "        <#if chainModel>\n"
                + "        return this;\n"
                + "        </#if>\n"
                + "    }\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "\n"
                + "<#if entityColumnConstant>\n"
                + "    <#list customAllFields as field>\n"
                + "    public static final String ${field.name?upper_case} = \"${field.name}\";\n"
                + "\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "<#if activeRecord>\n"
                + "    @Override\n"
                + "    public Serializable pkVal() {\n"
                + "    <#if keyPropertyName??>\n"
                + "        return this.${keyPropertyName};\n"
                + "    <#else>\n"
                + "        return null;\n"
                + "    </#if>\n"
                + "    }\n"
                + "</#if>\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    @Override\n"
                + "    public String toString() {\n"
                + "        return \"${originEntityName}{\" +\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field_index==0>\n"
                + "            \"${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        <#else>\n"
                + "            \", ${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        </#if>\n"
                + "    </#list>\n"
                + "        \"}\";\n"
                + "    }\n"
                + "</#if>\n"
                + "}"),
        PojoListRespVO("PojoListRespVO.ftl", "package ${package.Entity}.resp;\n"
                + "\n"
                + "<#if ifAddExcelPropertyAnno>\n"
                + "import com.alibaba.excel.annotation.ExcelProperty;\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "\n"
                + "<#list customImportPackages! as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} list resp\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} list resp\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}ListRespVO {\n"
                + "<#-- ----------  BEGIN 字段循环遍历  ---------->\n"
                + "<#list customAllFields as field>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#assign keyPropertyName=\"${field.propertyName}\"/>\n"
                + "    </#if>\n"
                + "\n"
                + "    <#if field.comment!?length gt 0>\n"
                + "    /**\n"
                + "     * ${field.comment}\n"
                + "     */\n"
                + "        <#if swagger>\n"
                + "    @ApiModelProperty(\"${field.comment}\")\n"
                + "        </#if>\n"
                + "        <#if ifAddExcelPropertyAnno>\n"
                + "    @ExcelProperty(\"${field.comment}\")\n"
                + "        </#if>\n"
                + "    </#if>\n"
                + "    private ${field.propertyType} ${field.propertyName};\n"
                + "</#list>\n"
                + "<#------------  END 字段循环遍历  ---------->\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field.propertyType == \"boolean\">\n"
                + "            <#assign getprefix=\"is\"/>\n"
                + "        <#else>\n"
                + "            <#assign getprefix=\"get\"/>\n"
                + "        </#if>\n"
                + "    public ${field.propertyType} ${getprefix}${field.capitalName}() {\n"
                + "        return ${field.propertyName};\n"
                + "    }\n"
                + "\n"
                + "    <#if chainModel>\n"
                + "    public ${originEntityName} set${field.capitalName}(${field.propertyType} ${field"
                + ".propertyName}) {\n"
                + "    <#else>\n"
                + "    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    </#if>\n"
                + "        this.${field.propertyName} = ${field.propertyName};\n"
                + "        <#if chainModel>\n"
                + "        return this;\n"
                + "        </#if>\n"
                + "    }\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "\n"
                + "<#if entityColumnConstant>\n"
                + "    <#list customAllFields as field>\n"
                + "    public static final String ${field.name?upper_case} = \"${field.name}\";\n"
                + "\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "<#if activeRecord>\n"
                + "    @Override\n"
                + "    public Serializable pkVal() {\n"
                + "    <#if keyPropertyName??>\n"
                + "        return this.${keyPropertyName};\n"
                + "    <#else>\n"
                + "        return null;\n"
                + "    </#if>\n"
                + "    }\n"
                + "</#if>\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    @Override\n"
                + "    public String toString() {\n"
                + "        return \"${originEntityName}{\" +\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field_index==0>\n"
                + "            \"${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        <#else>\n"
                + "            \", ${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        </#if>\n"
                + "    </#list>\n"
                + "        \"}\";\n"
                + "    }\n"
                + "</#if>\n"
                + "}"),
        PojoUpdateReqVO("PojoUpdateReqVO.ftl", "package ${package.Entity}.req;\n"
                + "\n"
                + "<#if swagger>\n"
                + "import io.swagger.annotations.ApiModel;\n"
                + "import io.swagger.annotations.ApiModelProperty;\n"
                + "</#if>\n"
                + "<#if entityLombokModel>\n"
                + "import lombok.Data;\n"
                + "import lombok.EqualsAndHashCode;\n"
                + "import JustryDeng_Placeholder.BaseDTO;\n"
                + "    <#if chainModel>\n"
                + "import lombok.experimental.Accessors;\n"
                + "    </#if>\n"
                + "</#if>\n"
                + "\n"
                + "<#list customImportPackages! as pkg>\n"
                + "import ${pkg};\n"
                + "</#list>\n"
                + "\n"
                + "/**\n"
                + " * <p>\n"
                + " * ${table.comment!} update req\n"
                + " * </p>\n"
                + " *\n"
                + " * @author ${author}\n"
                + " * @since ${date}\n"
                + " */\n"
                + "<#if entityLombokModel>\n"
                + "@Data\n"
                + "    <#if chainModel>\n"
                + "@Accessors(chain = true)\n"
                + "    </#if>\n"
                + "@EqualsAndHashCode(callSuper = true)\n"
                + "</#if>\n"
                + "<#if swagger>\n"
                + "@ApiModel(description = \"${table.comment!} update req\")\n"
                + "</#if>\n"
                + "public class ${originEntityName}UpdateReqVO extends BaseDTO {\n"
                + "<#-- ----------  BEGIN 字段循环遍历  ---------->\n"
                + "<#list customAllFields as field>\n"
                + "    <#if field.keyFlag>\n"
                + "        <#assign keyPropertyName=\"${field.propertyName}\"/>\n"
                + "    </#if>\n"
                + "\n"
                + "    <#if field.comment!?length gt 0>\n"
                + "    /**\n"
                + "     * ${field.comment}\n"
                + "     */\n"
                + "        <#if swagger>\n"
                + "    @ApiModelProperty(\"${field.comment}\")\n"
                + "        </#if>\n"
                + "    </#if>\n"
                + "    private ${field.propertyType} ${field.propertyName};\n"
                + "</#list>\n"
                + "<#------------  END 字段循环遍历  ---------->\n"
                + "<#if !entityLombokModel>\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field.propertyType == \"boolean\">\n"
                + "            <#assign getprefix=\"is\"/>\n"
                + "        <#else>\n"
                + "            <#assign getprefix=\"get\"/>\n"
                + "        </#if>\n"
                + "    public ${field.propertyType} ${getprefix}${field.capitalName}() {\n"
                + "        return ${field.propertyName};\n"
                + "    }\n"
                + "\n"
                + "    <#if chainModel>\n"
                + "    public ${originEntityName} set${field.capitalName}(${field.propertyType} ${field"
                + ".propertyName}) {\n"
                + "    <#else>\n"
                + "    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {\n"
                + "    </#if>\n"
                + "        this.${field.propertyName} = ${field.propertyName};\n"
                + "        <#if chainModel>\n"
                + "        return this;\n"
                + "        </#if>\n"
                + "    }\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "\n"
                + "<#if entityColumnConstant>\n"
                + "    <#list customAllFields as field>\n"
                + "    public static final String ${field.name?upper_case} = \"${field.name}\";\n"
                + "\n"
                + "    </#list>\n"
                + "</#if>\n"
                + "<#if activeRecord>\n"
                + "    @Override\n"
                + "    public Serializable pkVal() {\n"
                + "    <#if keyPropertyName??>\n"
                + "        return this.${keyPropertyName};\n"
                + "    <#else>\n"
                + "        return null;\n"
                + "    </#if>\n"
                + "    }\n"
                + "</#if>\n"
                + "<#if !entityLombokModel>\n"
                + "\n"
                + "    @Override\n"
                + "    public String toString() {\n"
                + "        return \"${originEntityName}{\" +\n"
                + "    <#list customAllFields as field>\n"
                + "        <#if field_index==0>\n"
                + "            \"${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        <#else>\n"
                + "            \", ${field.propertyName}=\" + ${field.propertyName} +\n"
                + "        </#if>\n"
                + "    </#list>\n"
                + "        \"}\";\n"
                + "    }\n"
                + "</#if>\n"
                + "}"),
        ;
        private final String name;
        private final String content;
        
        JustryDengTemplates(String name, String content) {
            this.name = name;
            this.content = content;
        }
    }
}